﻿using Base.Core20;
using Base.Core20.Enums;
using Base.Core20.Flows;
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using Winservice.demo.Models.Entities;
using Winservice.demo.Queue;
using System.Threading.Tasks;

namespace Winservice.demo.Common
{
    /// <summary>
    /// 公共类库
    /// </summary>
    public class Utils
    {
        /// <summary>
        /// 声明一个已经是否声明自身类的对象
        /// </summary>
        private volatile static Utils _instance = null;

        /// <summary>
        /// 锁
        /// </summary>
        private static readonly object lockHelper = new object();

        /// <summary>
        /// 
        /// </summary>
        private Utils() { }

        /// <summary>
        /// 创建单实例（函数方式）
        /// </summary>
        /// <returns></returns>
        public static Utils CreateInstance()
        {
            if (_instance == null)
            {
                lock (lockHelper)
                {
                    if (_instance == null)
                        _instance = new Utils();
                }
            }
            return _instance;
        }

        /// <summary>
        /// 默认最小时间(1753-11-11 11:11:11)
        /// </summary>
        public readonly string DefaultMinDateTime = "1753-11-11 11:11:11";

        /// <summary>
        /// 默认最小时间(1753-11-11)
        /// </summary>
        public readonly string DefaultMinDate = "1753-11-11";

        /// <summary>
        /// 读取数据库类型 mysql, oracle, sqlserver, access
        /// </summary>
        /// <returns></returns>
        public DBTYPE ReadTypeOfDataBase()
        {
            DBTYPE dbType = DBTYPE.None;
            string s = Directory.GetCurrentDirectory() + @"\Config\System\";

            XmlDocument doc = new XmlDocument();

            string type = "";

            doc.Load(s + "DataBase.xml");

            var nodes = doc.SelectSingleNode("database").ChildNodes;

            foreach (XmlNode item in nodes)
            {
                XmlElement xe = (XmlElement)item;
                if (xe.Name == "type")
                {
                    type = xe.InnerText;
                    break;
                }
            }

            switch (type.ToLower())
            {
                case "mysql":
                    dbType = DBTYPE.MySql;
                    break;
                case "oracle":
                    dbType = DBTYPE.Oracle;
                    break;
                case "sqlserver":
                    dbType = DBTYPE.SqlServer;
                    break;
                case "access":
                    dbType = DBTYPE.Access;
                    break;
            }
            return dbType;
        }

        /// <summary>
        /// 获取 AppConfig 对象
        /// </summary>
        /// <returns></returns>
        public AppConfig GetAppConfig()
        {
            AppConfig appConfig = new AppConfig();

            string s = Directory.GetCurrentDirectory() + @"\Config\System\";

            XmlDocument doc = new XmlDocument();

            //doc.Load(s + "AppConfig.xml");

            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true; //忽略文档里面的注释

            using (XmlReader reader = XmlReader.Create(s + "AppConfig.xml", settings))
            {
                doc.Load(reader);

                var nodes = doc.SelectSingleNode("Settings").ChildNodes;
                foreach (XmlNode item in nodes)
                {
                    XmlElement xe = (XmlElement)item;
                    if (xe.Name == "SerName")
                    {
                        appConfig.SER_NAME = xe.InnerText;
                    }
                    if (xe.Name == "IntervalTime")
                    {
                        appConfig.INTERVAL_TIME = string.IsNullOrEmpty(xe.InnerText) ? 0 : Convert.ToInt32(xe.InnerText);
                    }
                    if (xe.Name == "Times")
                    {
                        appConfig.TIMES = xe.InnerText;
                    }
                    if (xe.Name == "DaysByDelete")
                    {
                        appConfig.DAYS_BY_DELETE = xe.InnerText;
                    }
                    if (xe.Name == "MailToAdmin")
                    {
                        appConfig.MAIL_TO_ADMIN = xe.InnerText;
                    }
                    if (xe.Name == "A5BaseCoreApi")
                    {
                        appConfig.A5_BASE_CORE_API = xe.InnerText;
                    }
                }

                //reader.Close();
            }
            return appConfig;
        }

        /// <summary>
        /// 获取 CustomProcess 对象
        /// </summary>
        /// <returns></returns>
        public async Task<List<CustomProcess>> GetCustomProcessAsync()
        {
            List<CustomProcess> list = new List<CustomProcess>();
            XmlDocument doc = new XmlDocument();
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true; //忽略文档里面的注释
            using (XmlReader reader = XmlReader.Create(Directory.GetCurrentDirectory() + "/Config/System/CustomProcess.xml", settings))
            {
                doc.Load(reader);
                var nodes = doc.SelectSingleNode("Settings").ChildNodes;
                foreach (XmlNode item in nodes)
                {
                    XmlElement xe = (XmlElement)item;
                    list.Add(new CustomProcess()
                    {
                        ProcessName = xe.GetAttribute("ProcessName"),
                        Sql = xe.InnerText
                    });
                }
            }
            return await Task.FromResult(list);
        }

        /// <summary>
        /// 读取数据库链接字符串
        /// </summary>
        /// <returns></returns>
        public string ReadConnectionStrOfDataBase()
        {
            string s = Directory.GetCurrentDirectory() + @"\Config\System\";

            XmlDocument doc = new XmlDocument();

            string connectionStr = "";

            doc.Load(s + "DataBase.xml");

            var nodes = doc.SelectSingleNode("database").ChildNodes;

            foreach (XmlNode item in nodes)
            {
                XmlElement xe = (XmlElement)item;
                if (xe.Name == "connectionStr")
                {
                    connectionStr = xe.InnerText;
                    break;
                }
            }
            return connectionStr;
        }

        /// <summary>
        /// 是否到时间进行执行
        /// </summary>
        /// <param name="appConfig">配置的信息</param>
        /// <param name="hour">当前时间（小时）</param>
        /// <returns>true：时间已到；false：时间未到；</returns>
        public bool TimeOut(AppConfig appConfig, string hour)
        {
            string times = appConfig.TIMES;
            if (times == null || times.Trim().Length <= 0)
            {
                return false;
            }
            if (times.IndexOf('|') > 0)
            {
                foreach (string t in times.Split('|'))
                {
                    if (t == hour)
                    {
                        return true;
                    }
                }
            }
            else if (times.Equals(hour))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 从文件读取 Stream
        /// </summary>
        /// <param name="fileFullName">文件地址路径（路径+文件名称+文件后缀）</param>
        /// <returns></returns>
        public Stream FileToStream(string fileFullName)
        {
            // 打开文件  
            using (FileStream fileStream = new FileStream(fileFullName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                // 读取文件的 byte[]  
                byte[] bytes = new byte[fileStream.Length];
                fileStream.Read(bytes, 0, bytes.Length);
                fileStream.Close();
                // 把 byte[] 转换成 Stream  
                //using (Stream stream = new MemoryStream(bytes))
                //{
                //    return stream;
                //}
                Stream stream = new MemoryStream(bytes);
                return stream;
            }
        }

        ///// <summary>
        ///// 获取异常信息（包括堆栈）
        ///// </summary>
        ///// <param name="methodBase">System.Reflection.MethodBase.GetCurrentMethod()</param>
        ///// <param name="exception">ce</param>
        ///// <param name="message">自定义信息（没有信息，可以为空字符串）</param>
        ///// <returns>返回异常信息（包括堆栈）</returns>
        //public string GetExceptionMessage(MethodBase methodBase, Exception exception, string message)
        //{
        //    //System.Reflection.MethodBase methodBase = System.Reflection.MethodBase.GetCurrentMethod();
        //    //string className = methodBase.ReflectedType.BaseType.FullName == "System.Object" ? methodBase.ReflectedType.FullName : methodBase.ReflectedType.BaseType.FullName;
        //    string className = methodBase.ReflectedType.FullName;
        //    string methodName = methodBase.Name;
        //    string allMessage = string.Format("\r\n异常综合信息（类：{0}；函数名称：{1}；）：\r\n", className, methodName);
        //    if (exception != null)
        //    {
        //        allMessage += "---------------------------------\r\n";
        //        allMessage += "异常信息：\r\n\r\n";
        //        allMessage += string.Format("{0}\r\n", exception.Message);
        //        allMessage += "---------------------------------\r\n";
        //        allMessage += "堆栈信息：\r\n\r\n";
        //        allMessage += string.Format("{0}\r\n", exception.StackTrace);
        //        allMessage += "---------------------------------\r\n";
        //    }
        //    if (message != null && message.Trim().Length > 0)
        //    {
        //        allMessage += "=================================\r\n";
        //        allMessage += "自定义信息：\r\n\r\n";
        //        allMessage += string.Format("{0}\r\n", message);
        //        allMessage += "=================================\r\n";
        //    }
        //    return allMessage;
        //}

        /// <summary>
        /// 格式化下 节点名称（把空格及.替换成_）
        /// </summary>
        public string StepLabelFormat(string stepLabel)
        {
            return stepLabel.Trim().Replace(' ', '_').Replace('.', '_');
        }

        /// <summary>
        /// 获取 变量 集合
        /// </summary>
        /// <param name="variables">variables</param>
        /// <returns></returns>
        public List<Variable> GetVariables(string variables)
        {
            List<Variable> list = new List<Variable>();
            if (variables != null && variables.Trim().Length > 0)
            {
                foreach (string var in variables.Split('|'))
                {
                    if (var != null && var.Trim().Length > 0)
                    {
                        string variableName = var.Split(':')[0];
                        string variableValue = var.Split(':')[1];
                        string variableType = var.Split(':')[2];
                        string sort = var.Split(':')[3];

                        Variable v = new Variable();
                        v.VARIABLE_NAME = variableName;
                        //v.VARIABLE_VALUE = variableValue.Split('*');
                        v.VARIABLE_VALUE = variableValue;
                        if (variableType == "0")
                        {
                            v.VARIABLE_TYPE = VARIABLE_TYPE_Enum.APPROVAL;
                        }
                        else if (variableType == "1")
                        {
                            v.VARIABLE_TYPE = VARIABLE_TYPE_Enum.REJECTED;
                        }
                        else if (variableType == "3")
                        {
                            v.VARIABLE_TYPE = VARIABLE_TYPE_Enum.PAUSE;
                        }
                        else
                        {
                            v.VARIABLE_TYPE = VARIABLE_TYPE_Enum.ALL;
                        }
                        v.SORT = Convert.ToInt32(sort);
                        list.Add(v);
                    }
                }
            }
            return list;
        }

        /// <summary>
        /// 获取 会签任务 集合
        /// </summary>
        /// <param name="param">param</param>
        /// <returns></returns>
        public List<SignTask> GetSignTasks(string param)
        {
            List<SignTask> list = new List<SignTask>();
            if (param != null && param.Trim().Length > 0)
            {
                foreach (string p in param.Split('|'))
                {
                    if (p != null && p.Trim().Length > 0)
                    {
                        string taskID = p.Split(':')[0];
                        string taskStatus = p.Split(':')[1];
                        string opinion = p.Split(':')[2];

                        SignTask m = new SignTask();
                        m.TASK_ID = taskID;
                        m.TASK_STATUS = Convert.ToInt32(taskStatus);
                        m.OPINION = Convert.ToInt32(opinion);
                        list.Add(m);
                    }
                }
            }
            return list;
        }

        /// <summary>
        /// 获取得到 新的 变量集合
        /// </summary>
        /// <param name="queueTask">队列任务对象</param>
        /// <param name="variableList">变量集合</param>
        /// <param name="signTaskList">会签任务集合</param>
        /// <param name="isSignEndStep">会签节点 是否 办结(普通节点不算在内)</param>
        /// <param name="finalOpinion">当前节点（包括会签）是否拒绝（如果拒绝的话，是不允许 FLOW_INCIDENT_STATUS=103 的）</param>
        /// <returns></returns>
        public List<Var> GetNewVariableList(QueueTask queueTask, List<Variable> variableList, List<SignTask> signTaskList, out bool isSignEndStep, out OPINION_Enum finalOpinion)
        {
            // 有个 漏洞，就是 并发的时候，怎么办。怎么告知，这个会签节点 已经 不需要再次 处理了。
            // 以上 漏铜 已经解决，就是用 FLOW_COUNTERSIGN_FINISHED 表 来解决 该问题，具体 看 函数 GetSignFinished （1033：自动办结）

            isSignEndStep = false; //是否是已经结束的会签节点

            finalOpinion = OPINION_Enum.APPROVAL;  //最终意见（默认给同意）

            List<Var> newVariableList = new List<Var>();
            if (queueTask.FIRST_SIGN_COUNT == 0)
            {
                //当不是 会签的时候

                if (queueTask.OPINION == OPINION_Enum.REJECTED.GetHashCode())
                {
                    finalOpinion = OPINION_Enum.REJECTED;
                }

                variableList.ForEach(m =>
                {
                    if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.ALL)
                    {
                        //newVariableList.Add(m);
                        newVariableList.Add(new Var
                        {
                            VARIABLE_NAME = m.VARIABLE_NAME,
                            VARIABLE_VALUE = m.VARIABLE_VALUE
                        });
                    }

                    if (queueTask.OPINION == m.VARIABLE_TYPE.GetHashCode())
                    {
                        //newVariableList.Add(m);
                        newVariableList.Add(new Var
                        {
                            VARIABLE_NAME = m.VARIABLE_NAME,
                            VARIABLE_VALUE = m.VARIABLE_VALUE
                        });
                    }
                });
            }
            else
            {
                //当是 会签的时候
                //情况一：都要审批完成；
                if (queueTask.SIGN_TYPE == SIGN_TYPE_Enum.ALL.GetHashCode())
                {
                    //先 计算 总人数 是否 等于 FirstSignCount
                    if (signTaskList.Count == queueTask.FIRST_SIGN_COUNT)
                    {
                        isSignEndStep = true;  //*** 会签结束

                        //再 计算 会签意见 是否 都是 “同意”，如果是，则 走 “同意”变量；反之，走 “拒绝”变量；
                        bool isApproval = true;
                        foreach (SignTask t in signTaskList)
                        {
                            if (t.OPINION != 0)
                            {
                                isApproval = false;
                                break;
                            }
                        }

                        if (isApproval)
                        {
                            //走 “同意”变量
                            variableList.ForEach(m =>
                            {
                                if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.ALL)
                                {
                                    //newVariableList.Add(m);
                                    newVariableList.Add(new Var
                                    {
                                        VARIABLE_NAME = m.VARIABLE_NAME,
                                        VARIABLE_VALUE = m.VARIABLE_VALUE
                                    });
                                }

                                if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.APPROVAL)
                                {
                                    //newVariableList.Add(m);
                                    newVariableList.Add(new Var
                                    {
                                        VARIABLE_NAME = m.VARIABLE_NAME,
                                        VARIABLE_VALUE = m.VARIABLE_VALUE
                                    });
                                }
                            });
                        }
                        else
                        {
                            finalOpinion = OPINION_Enum.REJECTED;

                            //走 “拒绝”变量
                            variableList.ForEach(m =>
                            {
                                if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.ALL)
                                {
                                    //newVariableList.Add(m);
                                    newVariableList.Add(new Var
                                    {
                                        VARIABLE_NAME = m.VARIABLE_NAME,
                                        VARIABLE_VALUE = m.VARIABLE_VALUE
                                    });
                                }

                                if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.REJECTED)
                                {
                                    //newVariableList.Add(m);
                                    newVariableList.Add(new Var
                                    {
                                        VARIABLE_NAME = m.VARIABLE_NAME,
                                        VARIABLE_VALUE = m.VARIABLE_VALUE
                                    });
                                }
                            });
                        }

                    }
                    else
                    {
                        //就暂停呗
                        variableList.ForEach(m =>
                        {
                            if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.ALL
                            || m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.PAUSE)
                            {
                                //newVariableList.Add(m);
                                newVariableList.Add(new Var
                                {
                                    VARIABLE_NAME = m.VARIABLE_NAME,
                                    VARIABLE_VALUE = m.VARIABLE_VALUE
                                });
                            }
                        });
                    }
                }
                //情况二：同意 一次 就得 往下走；反之，往 拒绝 方向走；
                else if (queueTask.SIGN_TYPE == SIGN_TYPE_Enum.APPROVAL_ONE_TIME.GetHashCode())
                {
                    bool isApproval = false;
                    foreach (SignTask t in signTaskList)
                    {
                        if (t.OPINION == 0)
                        {
                            isApproval = true;
                            break;
                        }
                    }
                    if (isApproval)
                    {
                        isSignEndStep = true;  //*** 会签结束

                        //走 “同意”变量
                        variableList.ForEach(m =>
                        {
                            if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.ALL)
                            {
                                //newVariableList.Add(m);
                                newVariableList.Add(new Var
                                {
                                    VARIABLE_NAME = m.VARIABLE_NAME,
                                    VARIABLE_VALUE = m.VARIABLE_VALUE
                                });
                            }

                            if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.APPROVAL)
                            {
                                //newVariableList.Add(m);
                                newVariableList.Add(new Var
                                {
                                    VARIABLE_NAME = m.VARIABLE_NAME,
                                    VARIABLE_VALUE = m.VARIABLE_VALUE
                                });
                            }
                        });
                    }
                    else
                    {
                        if (signTaskList.Count == queueTask.FIRST_SIGN_COUNT)
                        {
                            isSignEndStep = true;  //*** 会签结束

                            finalOpinion = OPINION_Enum.REJECTED;

                            //走 “拒绝”变量
                            variableList.ForEach(m =>
                            {
                                if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.ALL)
                                {
                                    //newVariableList.Add(m);
                                    newVariableList.Add(new Var
                                    {
                                        VARIABLE_NAME = m.VARIABLE_NAME,
                                        VARIABLE_VALUE = m.VARIABLE_VALUE
                                    });
                                }

                                if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.REJECTED)
                                {
                                    //newVariableList.Add(m);
                                    newVariableList.Add(new Var
                                    {
                                        VARIABLE_NAME = m.VARIABLE_NAME,
                                        VARIABLE_VALUE = m.VARIABLE_VALUE
                                    });
                                }
                            });
                        }
                        else
                        {
                            //就暂停呗
                            variableList.ForEach(m =>
                            {
                                if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.ALL
                                || m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.PAUSE)
                                {
                                    //newVariableList.Add(m);
                                    newVariableList.Add(new Var
                                    {
                                        VARIABLE_NAME = m.VARIABLE_NAME,
                                        VARIABLE_VALUE = m.VARIABLE_VALUE
                                    });
                                }
                            });
                        }
                    }
                }
                //情况三：拒绝 一次 就得 往下走；反之，往 同意 方向走；
                else if (queueTask.SIGN_TYPE == SIGN_TYPE_Enum.REJECTED_ONE_TIME.GetHashCode())
                {
                    bool isRejected = false;
                    foreach (SignTask t in signTaskList)
                    {
                        if (t.OPINION == 1)
                        {
                            isRejected = true;
                            break;
                        }
                    }
                    if (isRejected)
                    {
                        isSignEndStep = true;  //*** 会签结束

                        finalOpinion = OPINION_Enum.REJECTED;

                        //走 “拒绝”变量
                        variableList.ForEach(m =>
                        {
                            if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.ALL)
                            {
                                //newVariableList.Add(m);
                                newVariableList.Add(new Var
                                {
                                    VARIABLE_NAME = m.VARIABLE_NAME,
                                    VARIABLE_VALUE = m.VARIABLE_VALUE
                                });
                            }

                            if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.REJECTED)
                            {
                                //newVariableList.Add(m);
                                newVariableList.Add(new Var
                                {
                                    VARIABLE_NAME = m.VARIABLE_NAME,
                                    VARIABLE_VALUE = m.VARIABLE_VALUE
                                });
                            }
                        });
                    }
                    else
                    {
                        if (signTaskList.Count == queueTask.FIRST_SIGN_COUNT)
                        {
                            isSignEndStep = true;  //*** 会签结束

                            //走 “同意”变量
                            variableList.ForEach(m =>
                            {
                                if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.ALL)
                                {
                                    //newVariableList.Add(m);
                                    newVariableList.Add(new Var
                                    {
                                        VARIABLE_NAME = m.VARIABLE_NAME,
                                        VARIABLE_VALUE = m.VARIABLE_VALUE
                                    });
                                }

                                if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.APPROVAL)
                                {
                                    //newVariableList.Add(m);
                                    newVariableList.Add(new Var
                                    {
                                        VARIABLE_NAME = m.VARIABLE_NAME,
                                        VARIABLE_VALUE = m.VARIABLE_VALUE
                                    });
                                }
                            });
                        }
                        else
                        {
                            //就暂停呗
                            variableList.ForEach(m =>
                            {
                                if (m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.ALL
                                || m.VARIABLE_TYPE == VARIABLE_TYPE_Enum.PAUSE)
                                {
                                    //newVariableList.Add(m);
                                    newVariableList.Add(new Var
                                    {
                                        VARIABLE_NAME = m.VARIABLE_NAME,
                                        VARIABLE_VALUE = m.VARIABLE_VALUE
                                    });
                                }
                            });
                        }
                    }
                }
                else
                {
                    throw new Exception("没法得到 queueTask.SignType 的枚举（FLOW_TASK_ID:" + queueTask.FLOW_TASK_ID + "）");
                }
            }
            return newVariableList;
        }

    }
}
